package net.bingosoft.common.server;

import java.io.File;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;

import net.bingosoft.common.config.Config;
import net.bingosoft.common.util.FileHelper;

import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Embedded;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
 * 2008-1-9 上午10:06:54
 * Author:yangdongyu(yangdy@bingosoft.net)
 * ReadMe:内嵌的tomcat,能够快速启动和关闭
 * ChangeLog:
 */
public class EmbeddedTomcat {
	private static final Log log = LogFactory.getLog(EmbeddedTomcat.class);
	private static Embedded tomcat;
	private static Host host;
	private boolean isRunning = false;
	private static String CATALINA_HOME = FileHelper.getFilePath(Config.getString("CATALINA_HOME","Embedded/Tomcat"));
	private static String SERVER_IP = Config.getString("SERVER_IP", "localhost");

	private static int SERVER_PORT = Config.getInt("SERVER_PORT", 8080);
	private static EmbeddedTomcat instance;
	private static Map <String,String>ctxPathToWebRootPathMap = new HashMap<String, String>();


	public static synchronized EmbeddedTomcat getInstance() throws Exception {
		if(instance == null){
			instance = new EmbeddedTomcat();	
		}
		return instance;
	}

	/**
	 * Default Constructor
	 * @throws Exception 
	 *
	 */
	private EmbeddedTomcat() throws Exception {
		if(EmbeddedTomcat.tomcat == null){
			EmbeddedTomcat.tomcat = createTomcat();
		}
	}

	/**
	 * This method Starts the Tomcat server.
	 * @return 
	 * @throws Exception 
	 */
	private Embedded createTomcat() throws Exception{
		tomcat = new Embedded();
		tomcat.setCatalinaHome(CATALINA_HOME);
		log.debug("CATALINA_HOME :" + tomcat.getCatalinaHome());
		Engine engine = tomcat.createEngine(); 
		engine.setName("Catalina"); 
		host = tomcat.createHost(SERVER_IP, CATALINA_HOME);
		engine.addChild(host); 
		engine.setDefaultHost(host.getName()); 
		tomcat.addEngine(engine);	
		Connector connector = tomcat.createConnector(InetAddress.getByName(SERVER_IP), SERVER_PORT, false);
		tomcat.addConnector(connector);
		if(SERVER_IP.equals("localhost")){
			Connector addressConnector = tomcat.createConnector(InetAddress.getLocalHost().getHostAddress(), SERVER_PORT, false);
			tomcat.addConnector(addressConnector);
		}
		connector.setURIEncoding(Config.getString("CONNECTOR_URIENCODING", "UTF-8"));
		connector.setUseBodyEncodingForURI(Config.getBoolean("CONNECTOR_useBodyEncodingForURI", true));
		return tomcat; 
	}

	public EmbeddedTomcat addContext(String ctxPath,String prjWebRootPath,boolean reloadable){
		Context context = tomcat.createContext(ctxPath, prjWebRootPath); 
		context.setReloadable(reloadable);
		host.addChild(context);
		return this;
	}
	/**
	 * This method Starts the Tomcat server.
	 */
	public void start() throws Exception {

		tomcat.start();
		this.isRunning = true;
	}

	/**
	 * 添加新的应用
	 * @param contextPath
	 * @param webRootDir
	 * @return
	 * @throws Exception
	 */
	public EmbeddedTomcat addApplication(String contextPath,String webRootDir) throws Exception{
		EmbeddedTomcat instance = getInstance();
		EmbeddedTomcat.ctxPathToWebRootPathMap.put(contextPath, webRootDir);
		return instance;
	}
	/**
	 * This method Stops the Tomcat server.
	 */
	public void stop() throws Exception {
		tomcat.stop();
		this.isRunning = false;
	}

	public boolean isRunning() {
		return isRunning;
	}

	/**
	 * 获取默认的上下文,即项目的名称
	 * @return
	 */
	public static String getDefaultContext(){
		String DEFAULT_CTXPATH =  Config.getString("DEFAULT_CTXPATH");
		if(DEFAULT_CTXPATH == null){
			DEFAULT_CTXPATH = new File("").getAbsolutePath();
			DEFAULT_CTXPATH = "/" + DEFAULT_CTXPATH.substring(DEFAULT_CTXPATH.lastIndexOf('\\')+1);

		}
		return DEFAULT_CTXPATH;
	}
	/**
	 * 启动多个tomcat应用
	 * @param ctxPathToWebRootPathMap
	 */
	public  void run(){
		try {
			long startTime = System.currentTimeMillis();
			EmbeddedTomcat tomcat = getInstance();
			String defaultCtxPath = null;

			if(ctxPathToWebRootPathMap == null || ctxPathToWebRootPathMap.isEmpty()) {
				String webRootPath = FileHelper.getFilePath(Config.getString("DEFAULT_PROJECT_WEBROOT_PATH","WebRoot"));
				defaultCtxPath = getDefaultContext();
				tomcat.addContext(defaultCtxPath,webRootPath ,true);
			}else{
				boolean isFirstContext = true;
				for(String ctxPath : ctxPathToWebRootPathMap.keySet()){
					if(isFirstContext){
						defaultCtxPath = ctxPath;
						isFirstContext = false;
					}
					String webRootPath = FileHelper.getFilePath(ctxPathToWebRootPathMap.get(ctxPath));
					tomcat.addContext(ctxPath,webRootPath ,true);
					log.debug( "请在地址栏输入 [ " + "http://"+ SERVER_IP + ":" + ((SERVER_PORT == 80)? "":SERVER_PORT ) + ctxPath + " ]访问您的应用...");
				}
			}			

			tomcat.start();
			log.debug("DEFAULT_PROJECT_WEBROOT_PATH :" + defaultCtxPath);
			String projectURL = "http://"+ SERVER_IP + ":" + ((SERVER_PORT == 80)? "":SERVER_PORT ) + defaultCtxPath;
			log.debug("Tomcat成功启动,耗时" + (System.currentTimeMillis() - startTime) + " ms");
			//打开第一个应用			
			String os = System.getProperty("os.name");
			if(os != null && os.startsWith("Windows")){
				try{
					//调用动态连接库,打开浏览器
					Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + projectURL );
				}catch(Exception ex){
					//忽略打开浏览器的错误,如果打不开,让用户输入地址打开
					log.debug("请在地址栏输入 [ "  +projectURL + " ]访问您的应用...");
				}
			}

		}catch( Exception e ) {
			log.error("启动tomcat出错...",e);
			System.exit(0);
		}
	}
	public static void main(String[] args) throws Exception {
		getInstance().run();
	}



}